﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.Threading;
using System.Threading.Tasks;
using System.Xml;
using System.Web;
using KC.DataAccess.Global;
using BLL = KC.Business.Articleulator.Articleulator;

namespace KC.Presentation.Articleulator
{
	public partial class Articleulator2 : Form
	{
		private readonly static string ConnStr = System.Configuration.ConfigurationManager.ConnectionStrings["SQL"].ConnectionString, ConnStrBS = System.Configuration.ConfigurationManager.ConnectionStrings["BS"].ConnectionString;
		private const int MaxPageSize = 65536;
		private int NumParallelism = 2;
		private DateTime NextPublish = DateTime.MinValue;

		public Articleulator2()
		{
			InitializeComponent();
		}
		private void Articleulator2_Load(object sender, EventArgs e)
		{
			ddlUsers.DataSource = Global.CallSql_Query(ConnStrBS, "select ID, Displayname from users order by id");
			ddlUsers.DisplayMember = "Displayname";
			ddlUsers.ValueMember = "ID";
		}
		private void tWorkers_Tick(object sender, EventArgs e)
		{
			// Auto Spider
			if (!cbAutoSpider.Checked && bgAutoSpider.IsBusy) bgAutoSpider.CancelAsync();
			else if (cbAutoSpider.Checked && !bgAutoSpider.IsBusy) bgAutoSpider.RunWorkerAsync();

			// Auto Parse
			if (!cbAutoParse.Checked && bgAutoParse.IsBusy) bgAutoParse.CancelAsync();
			else if (cbAutoParse.Checked && !bgAutoParse.IsBusy) bgAutoParse.RunWorkerAsync();

			// Auto Generate
			if (!cbAutoGenerate.Checked && bgAutoGenerate.IsBusy) bgAutoGenerate.CancelAsync();
			else if (cbAutoGenerate.Checked && !bgAutoGenerate.IsBusy) bgAutoGenerate.RunWorkerAsync();

			// Auto Publish
			if (!cbAutoPublish.Checked && bgAutoPublish.IsBusy) bgAutoPublish.CancelAsync();
			if (cbAutoPublish.Checked && !bgAutoPublish.IsBusy && NextPublish < DateTime.Now)
				try { bgAutoPublish.RunWorkerAsync(); }
				catch { } // sometimes doesn't detect IsBusy correctly
		}
		private void ddlUsers_SelectedIndexChanged(object sender, EventArgs e)
		{
			ddlBlogs.DataSource = Global.CallSql_Query(ConnStrBS, "select ID, Name from blogs where id in (select blogid from userroles where userid=" + ((DataRowView)ddlUsers.SelectedItem)["ID"] + ") order by name");
			ddlBlogs.DisplayMember = "Name";
			ddlBlogs.ValueMember = "ID";
		}

		#region AutoSpider
		private void bgAutoSpider_DoWork(object sender, DoWorkEventArgs e)
		{
			List<DataRow> rows = BLL.GetLinksToSpider();
			double curRow = 0;
			Parallel.ForEach(rows, dr => {
				if (bgAutoSpider.CancellationPending) return;
				BLL.SpiderLink(dr);
				curRow++;
				bgAutoSpider.ReportProgress((int)(100 * (curRow / (double)rows.Count)), "Spidering " + dr["ToURL"].ToString()); });
		}
		private void bgAutoSpider_ProgressChanged(object sender, ProgressChangedEventArgs e)
		{
			try {
				pbAutoSpider.Value = e.ProgressPercentage < 0 ? 0 : e.ProgressPercentage < 100 ? e.ProgressPercentage : 100;
				AddText((string)e.UserState);
				lblAutoSpider.Text = (string)e.UserState; }
			catch { }
		}
		private void bgAutoSpider_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
		{
			pbAutoSpider.Value = 0;
			lblAutoSpider.Text = (e.Cancelled ? "Cancelled" : e.Error == null ? "Completed" : "Errored out") + " at " + DateTime.Now.ToString("h:mm:ss tt");
		}
		#endregion AutoSpider
		#region AutoParse
		private void bgAutoParse_DoWork(object sender, DoWorkEventArgs e)
		{
			List<DataRow> rows = BLL.GetBodiesToParse();
			double curRow = 0;
			Parallel.ForEach(rows, new ParallelOptions() { MaxDegreeOfParallelism=NumParallelism}, dr => {
				try {
					bgAutoParse.ReportProgress((int)(100 * (curRow / (double)rows.Count)), "Importing URL: " + dr["URL"].ToString());
					if (bgAutoParse.CancellationPending) return;
					curRow++;
					BLL.ParseBody(dr); }
				catch { return; } });
		}
		private void bgAutoParse_ProgressChanged(object sender, ProgressChangedEventArgs e)
		{
			try {
				pbAutoParse.Value = e.ProgressPercentage < 0 ? 0 : e.ProgressPercentage < 100 ? e.ProgressPercentage : 100;
				AddText((string)e.UserState);
				lblAutoParse.Text = (string)e.UserState; }
			catch { }
		}
		private void bgAutoParse_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
		{
			pbAutoParse.Value = 0;
			lblAutoParse.Text = (e.Cancelled ? "Cancelled" : e.Error == null ? "Completed" : "Errored out") + " at " + DateTime.Now.ToString("h:mm:ss tt");
		}
		#endregion AutoParse
		#region AutoGenerate
		private void bgAutoGenerate_DoWork(object sender, DoWorkEventArgs e)
		{
			List<DataRow> rows = BLL.GetSentencesToGenerate();
			double curRow = 0;
			Parallel.ForEach(rows, new ParallelOptions() { MaxDegreeOfParallelism = NumParallelism }, dr => {
				curRow++;
				bgAutoGenerate.ReportProgress((int)(100 * (curRow / (double)rows.Count)), dr["Sentence"].ToString());
				if (bgAutoGenerate.CancellationPending) return;
				BLL.GenerateSentence(dr); });
		}
		private void bgAutoGenerate_ProgressChanged(object sender, ProgressChangedEventArgs e)
		{
			try {
				pbAutoGenerate.Value = e.ProgressPercentage < 0 ? 0 : e.ProgressPercentage < 100 ? e.ProgressPercentage : 100;
				AddText((string)e.UserState);
				lblAutoGenerate.Text = (string)e.UserState; }
			catch { }
		}
		private void bgAutoGenerate_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
		{
			pbAutoGenerate.Value = 0;
			lblAutoGenerate.Text = (e.Cancelled ? "Cancelled" : e.Error == null ? "Completed" : "Errored out") + " at " + DateTime.Now.ToString("h:mm:ss tt");
		}
		#endregion AutoGenerate
		#region AutoPublish
		private void bgAutoPublish_DoWork(object sender, DoWorkEventArgs e)
		{
			string title = null;
			e.Result = new string[] { BLL.WriteBlogPost(out title), title };
		}
		private void bgAutoPublish_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
		{
			NextPublish = DateTime.Now.AddMilliseconds((int)TimeSpan.FromSeconds(new Random().Next(60 * 5, 60 * 30)).TotalMilliseconds);
			pbAutoPublish.Value = 0;
			string body = ((string[])e.Result)[0],  title = ((string[])e.Result)[1];
			Global.CallSql_Query(ConnStrBS, "insert into posts (authoruserid, blogid, createdate, modifydate, publishdate, body, title, excerpt, status, isallowcomments, friendlyname, posttype) values (" +
				((DataRowView)ddlUsers.SelectedItem)["ID"].ToString() + ", " + ((DataRowView)ddlBlogs.SelectedItem)["ID"].ToString() + ", getdate(), getdate(), getdate(), '" + body.Replace("'", "''").Trim() + "', '" +
				title.Replace("'", "''").Trim() + "', '" + body.Substring(0, 255).Replace("'", "''").Trim() + "', 'Active', 1, '" + HttpUtility.UrlEncode(title).Replace("'", "''") + "','1')");
			AddText(body);
			lblAutoPublish.Text = (e.Cancelled ? "Cancelled" : e.Error == null ? "Completed" : "Errored out") + " at " + DateTime.Now.ToString("h:mm:ss tt") + ". Next publish " + NextPublish.ToString("h:mm:ss tt");
		}
		#endregion AutoPublish

		private void AddText(string txt)
		{
			txtResults.Text += txt + "\r\n";
			if (txtResults.Text.Length > 1536)
				txtResults.Text = txtResults.Text.Substring(txtResults.Text.Length - 1024);
			txtResults.SelectionStart = txtResults.Text.Length;
			txtResults.ScrollToCaret();
		}
	}
}